package com.company;

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.*;

/**
 * 超时匹配
 * @param <T>
 */
public abstract class TimeoutMatch<T> extends Thread implements Match<T> {

    /**
     * 匹配超时时间
     */
    private final long timeout;
    private final int capacity;
    private final ExecutorService executorService;
    private final LinkedBlockingDeque<T> deque = new LinkedBlockingDeque<>();

    public TimeoutMatch(int capacity, long timeout){
        this(capacity,timeout,Executors.newSingleThreadExecutor());
    }


    public TimeoutMatch(int capacity, long timeout,ExecutorService executorService){
        this.capacity = capacity;
        this.timeout = timeout;

        this.executorService = executorService;
        start();
    }

    @Override
    public void add(T ele){
        deque.push(ele);
    }

    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()){
            try {
                T start = deque.take();
                System.out.println("匹配开始");

                Future<Set<T>> submit = executorService.submit(new Task(start));
                try {
                    Set<T> list = submit.get(timeout, TimeUnit.SECONDS);
                    success(list);
                }catch (TimeoutException e) {
                    submit.cancel(true);
                }catch (Exception e){
                    e.printStackTrace();
                }

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    private class Task implements Callable<Set<T>>{

        private final T start;

        public Task(T start){
            this.start = start;
        }

        @Override
        public Set<T> call() {
            Set<T> list = new LinkedHashSet<>(capacity);
            list.add(start);
            System.out.println("放入临时匹配队列" + start);

            try {
                while (list.size() != capacity){
                    T ele = deque.take();
                    list.add(ele);
                    System.out.println("放入临时匹配队列" + ele);
                }
            }catch (InterruptedException e) {
                fail(list);
            }

            return list;
        }
    }
}
